/*
 * RootNodePool.java
 *
 * Created on 01 March 2005, 19:40
 */

package org.datamining.guha.utils;

import org.apache.commons.logging.*;
import org.datamining.guha.model.node.Node;
import org.datamining.guha.model.node.NodeFactory;

/**
 * This class serves as a pool of temporary root Nodes.
 * <p>
 * Inspiration taken from book: Java - performance tuning, Jack Shirazi, O'Rielly 2003.
 * See page 114 in Czech edition.
 *
 * @author Lukas Vlcek
 */
public class RootNodePool {
    
	private Log log = LogFactory.getLog(getClass());
	
	private NodeFactory nodeFactory;
    private Node[] pool;
    private boolean[] inUse;
    
    
    /** Creates a new instance of RootNodePool */
    public RootNodePool(int initSize, NodeFactory nodeFactory) {
        pool = new Node[initSize];
        inUse = new boolean[initSize];
        for (int i = pool.length-1; i >= 0; i--) {
            if (log.isDebugEnabled()) log.debug("new TempRoot["+i+"] created.");
            //pool[i] = new Node(null,null,null,0);
            this.nodeFactory = nodeFactory;
            pool[i] = nodeFactory.getNode(null,null,null,0);
            inUse[i] = false;
        }
        if (log.isDebugEnabled()) log.debug("RootNodePool created.");
    }
    
    public synchronized Node getTempRoot() {
        for (int i = inUse.length-1; i >= 0; i--) {
            if (!inUse[i]) {
                if (log.isDebugEnabled()) log.debug("TempRoot["+i+"] used.");
                inUse[i] = true;
                return pool[i];
            }
        }
        
        // If we are here then all Nodes are in use and we need to create others.
        
        boolean[] old_inUse = inUse;
        inUse = new boolean[old_inUse.length+10];
        System.arraycopy(old_inUse, 0, inUse, 0, old_inUse.length);
        
        Node[] old_pool = pool;
        pool = new Node[old_pool.length+10];
        System.arraycopy(old_pool, 0, pool, 0, old_pool.length);
        
        for (int i = old_pool.length; i < pool.length; i++ ) {
            if (log.isDebugEnabled()) log.debug("new TempRoot["+i+"] created.");
            //pool[i] = new Node(null,null,null,0);
            pool[i] = nodeFactory.getNode(null,null,null,0);
            inUse[i] = false;
        }
        
        // alocation of last Node
        inUse[pool.length-1] = true;
        return pool[pool.length-1];
    }
    
    public synchronized void returnTempNode(Node n) {
        for (int i = inUse.length-1; i >= 0; i--) {
            if (pool[i] == n) {
                if (log.isDebugEnabled()) log.debug("TempRoot["+i+"] returned back.");
                // reset Node
                n.setParent(null);
                n.setFrequency(0);
                n.setNextLiteralNode(null);
                n.setPreviousLiteralNode(null);
                n.getSuccessors().clear();
                // set not in use
                inUse[i] = false;
                return;
            }
        }
    }

}
